package com.gdth.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;

import com.gdth.service.listener.ServiceListener;
import com.gdth.utils.BaseAppUtil;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;

@SuppressLint("NewApi")
public class HeartServer {
	private static final String tag = "HeartServer";
	
	private static class HeartHelper {
		public final static HeartServer instance = new HeartServer();
	}
	
	public static final HeartServer getInstance() {
		return HeartHelper.instance;
	}
	
	private static final long HEART_BEAT_RATE = 8 * 1000;
	private String host;
	private int ports;
	
	/**上次发送时间**/
	private long sendTime = 0L;
	
	private int error = 0;
	private int connetion = 0;
	private int connetionSuccess = 0;
	private String token;
	private String DeviceId;
	private String os;
	
	/**
	 * 弱引用
	 */
	private WeakReference<Socket> mSocket;
	
	/** 读取线程 **/
	private ReadThread mReadThread;
	
	private ServiceListener mServiceListener;
	
	public HeartServer(){
		os = BaseAppUtil.getModelForOS();
	}
	
	public void start(){
//      启动心跳包
		if (token != null && host != null && ports != 0) {
			destroy();
			new InitSocketThread().start();
		}else {
			Log.e(tag, "本次未启动心跳包线程: token:"+token+",host:"+host+",ports:"+ports);
		}
	}
	
	/**
	 * 注销服务
	 */
	public void destroy(){
		mHandler.removeCallbacks(HeartRunnable);
        if (mReadThread != null)
        	mReadThread.release();
		
		if (mSocket != null)
			releaseLastSocket(mSocket);
	}
	
	/**
	 * 注销
	 * @param mSocket
	 */
	private void releaseLastSocket(WeakReference<Socket> mSocket) {
		try {
			if (null != mSocket) {
				Socket sk = mSocket.get();
				if (sk != null && !sk.isClosed()) {
					sk.close();
				}
				sk = null;
				mSocket = null;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void setServiceListener(ServiceListener mServiceListener){
		this.mServiceListener = mServiceListener;
	}
	
	/**
	 * 网络访问线程
	 * @author arvin
	 *
	 */
	class InitSocketThread extends Thread {
		@Override
		public void run() {
			super.run();
			Log.e(tag, "启动一个心跳包线程");
			initSocket();
		}
	}
	
	/**
	 * 初始化网络连接
	 */
	private void initSocket() {
		try {
			Socket so = new Socket(host, ports);
			mSocket = new WeakReference<Socket>(so);
			mReadThread = new ReadThread(so);
			mReadThread.start();
			mHandler.postDelayed(HeartRunnable, HEART_BEAT_RATE);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private Runnable HeartRunnable = new Runnable() {
		@Override
		public void run() {
			if (token != null) {
				if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
					String msg = "{\"token\":\""+token+"\",\"os\":\""+os+"\",\"DeviceId\":\""+DeviceId+"\"}";
					boolean isSuccess = sendMsg(msg);//"客户端时间:" + System.currentTimeMillis()
					if (!isSuccess) {
//						if (error > 100){
//							mServiceListener.pushNotificationText("连接超时：即将退出");
//							Intent intent=new Intent(BaseAction.action_heart_timeout);
//							mServiceListener.sendBroadcastByLocal(intent);
//							return;
//						}
						
						pushNotificationText("连接失败次数：" + error);
//						error += 1;
//						mHandler.removeCallbacks(this);
//						mReadThread.release();
//						releaseLastSocket(mSocket);
						
					} else {
						error = 0;
						connetion += 1;
						pushNotificationText("连接次数:" + connetion);
					}
					
				}
			}
//			mHandler.postDelayed(this, HEART_BEAT_RATE);
		}
	};
	

	public boolean sendMsg(String msg) {
		if (null == mSocket || null == mSocket.get()) {
			Log.w(tag, "mSocket为null");
			return false;
		}
		Socket soc = mSocket.get();
		try {
			if (!soc.isClosed() && !soc.isOutputShutdown()) {
				OutputStream os = soc.getOutputStream();
				String message = msg + "\r\n";
				os.write(message.getBytes());
				os.flush();
				sendTime = System.currentTimeMillis();
			} else {
				return false;
			}
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	
	
	/*******************************读取线程************************************/

	/**
	 * For heart Beat
	 */
	private Handler mHandler = new Handler();
	
	/**
	 * 心跳包接收线程
	 * @author arvin
	 *
	 */
	class ReadThread extends Thread {
		private WeakReference<Socket> mWeakSocket;
		private boolean isStart = true;

		public ReadThread(Socket socket) {
			mWeakSocket = new WeakReference<Socket>(socket);
		}

		public void release() {
			isStart = false;
			releaseLastSocket(mWeakSocket);
		}

		@Override
		public void run() {
			super.run();
			Socket socket = mWeakSocket.get();
			if (null != socket) {
				try {
					InputStream is = socket.getInputStream();
					byte[] buffer = new byte[1024 * 40];
					int length = 0;
					String message = null;
					while (!socket.isClosed() && !socket.isInputShutdown()
							&& isStart && ((length = is.read(buffer)) != -1)) {
						if (length > 0) {
							message = new String(Arrays.copyOf(buffer, length)).trim();
							
							//Log.e(tag, message);
							break;
						}
					}
					
					if (message != null) {
						if(message.equals("ok")){
							sendBroadcastByLocal(BaseAction.action_heart);
						} else if (message.equals("500")){
							pushNotificationText("app超时");
							sendBroadcastByLocal(BaseAction.action_heart_timeout);
						} else if (message.equals("200")){
							connetionSuccess += 1;
							pushNotificationText("连接次数成功" + connetionSuccess);
						} else {
							Intent intent=new Intent(BaseAction.action_message);
							intent.putExtra("message", message);
							sendBroadcastByLocal(intent);
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private void sendBroadcastByLocal(String arg0) {
		if (mServiceListener != null)
			mServiceListener.sendBroadcastByLocal(arg0);
	}
	
	private void sendBroadcastByLocal(Intent intent) {
		if (mServiceListener != null)
			mServiceListener.sendBroadcastByLocal(intent);
	}
	
	private void pushNotificationText(String arg0) {
		if (mServiceListener != null)
			mServiceListener.pushNotificationText(arg0);
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getPorts() {
		return ports;
	}

	public void setPorts(int ports) {
		this.ports = ports;
	}

	
	public void setToken(String token){
		this.token = token;
	}
	
	public void setDeviceId(String DeviceId){
		this.DeviceId = DeviceId;
	}
	
}
